var timer //定时器状态[监听同轨道高频发送弹幕]用来防抖
export default {
    data(){
        return {
            /* 方案1 */
            // 总共 5个 弹幕轨道 （最新）（轨道数量后面要动态插入，这样可以吧没有用到的轨道，不占用屏幕高度）
            danmu_list: [{
                cell_id: 1, //弹幕轨道id1
                danmu_cell: [] //弹幕轨道1 - 弹幕数据
            }],
            
            itemId: 1,//弹幕id
            
            flag: false,
            timeID: null,//定时器id
            num:null,//弹幕轨道编号发生编号时
            
            SameTime_danmuci:0,//弹幕在同一轨道，并且是一段时间内，发送次数不可以超过2个，否则会出现重叠
            
            screen_time:0,//弹幕进入屏幕的时间
            
            filter_count:0,//弹幕过滤数提示
            
            // 弹幕n轨道对应的flag（节流阀）
            danmu_unm:[{
                flag:true
            }],
            
            danmu_duration:this.duration,//弹幕持续时间
            
            danmuData:[],//存放用户发送的弹幕数据

            // 需要对弹幕数据通过发送时间进行排序，返回出去
        }
    },
    methods: {
        // refs调用方法（外面用户手动发送的弹幕）
        async add(obj){
			// #ifdef APP-PLUS-NVUE
			clearTimeout(this.timeID)
			let useradd = true //用于用户发送弹幕，不需要经过flag，直接发送
			//@1 执行发送弹幕
			this.danmulistAdd(obj,useradd)
			//@2 用户手动发送的弹幕，肯定要加个外边框的，参考优酷
			//@2.1 参数useradd_border_radius，这个值不计入回调出去参数里
			// #endif
        },
        // refs调用方法（系统自动发送的弹幕）
        async xtauto_add(obj){
            // #ifdef APP-PLUS-NVUE
            /* 系统自动发送弹幕，需要经过flag验证，用于数据量过大时，可以自动过滤发送弹幕，节约内存占用 */
            //@1 执行发送弹幕
            this.danmulistAdd(obj)
            // #endif
        },
        // 弹幕信息（测试用的）
        danmuText() {
            let item = {
                title: '我是一条弹幕哈哈哈哈哈哈',
                avatar: 'https://qlogo4.store.qq.com/qzone/2449253114/2449253114/100?1621494856',
                id: this.itemId++,
                //isend:false,//弹幕是否跑完了（跑完了就不渲染，节约内存）
            }
            return item
        },
        // 添加弹幕并发送（方案1）
        async danmulistAdd(obj,useradd){
            if (useradd==true){
                // 弹幕data，用来存放到 => 用户发送的弹幕数据里，并返回出去（或者外面videoplayer里调用的时候，返回出去）
                let data = {
                    text: obj.text,//弹幕内容
                    time: obj.time,//弹幕时间
                    color: obj.color||this.getRandomColor(),
                    avatar: obj.avatar,//弹幕图像
                    // 高级弹幕配置参数
                    border_radius: obj.border_radius,//圆角
                    border: obj.border,//边框色
                    background_image: obj.background_image,//背景线性渐变色
                    background_image_opacity: obj.background_image_opacity,//背景线性渐变色透明度
                    opacity: obj.opacity,//弹幕item透明度（当前发送的弹幕-整体透明度）
                }
                // 存放到 => 用户发送的弹幕数据里
                this.danmuData.push(data)
                // 将danmuData弹幕数据，返回出去
                let UserDanmuData = this.danmuData//用户发送的弹幕 -> 数据列表
               
                // 2022-0124 已去除下面的回调
                //this.$emit('changeUserDanmuAdd',UserDanmuData)

                /* ps => 系统自动发送的不用 返回出去 这样就可以吧新数据和老数据合并，新数据是用户手动发送的，老数据是已经有的数据，开发者在外面调用的时候，可以自主合并数据 */
            }
            
            
            // 计算弹幕文本长度
            let danmuTextLength = this.getDanmuTextbyteLength(obj.text)
            
            // 计算弹幕头像宽度 （头像是字体大小的2倍+2，如14*2+2=30 还要加上头像的外边距）
            let avatar_Widht = obj.avatar ? (this.FontSize*2)+2+this.avatar_m_right : 0
            
            // 计算弹幕宽度
            let danmu_Width = Number((danmuTextLength*this.FontSize)+avatar_Widht)//弹幕宽度（ps：弹幕文本长度 * 弹幕字体大小 + 弹幕头像宽度）
            // 入口参数（用于计算弹幕的头和尾巴...）
            let optinos = {
                duration: this.duration,//总时间（弹幕持续时间）
                Width: this.Width,//屏幕宽度
                danmu_Width,//弹幕宽度
            }
            
            // 计算弹幕的头和尾巴进入屏幕可视区需要的时间
            let ScreenTime = this.getDanmuItem_goScreenTime(optinos)
            this.screen_time = ScreenTime
            
            
            // 判断需要插入到的轨道id
            var num //n轨道
            var min = this.getDanmu_cell_length()
            if (min.xiangdeng == true) {
                // 所有轨道弹幕数相等时
                // 生成随机数 1-5 （用于插入n轨道）
                num = this.randomRange(1, this.danmu_cell_num)
            }else {
                // 所有轨道弹幕数不相等时（哪怕只有一个不相等）
                for (let i=0; i<min.cell_length.length; i++){
                    if (min.value == this.danmu_list[i].danmu_cell.length){
                        num = i+1//(从0开始)轨道弹幕item数量最小的一个
                    }
                }
            }
            
            // 获取弹幕信息，渲染到页面上
            let danmuItemText = {
                text: obj.text,//弹幕内容
                time: obj.time,//弹幕时间
                color: obj.color||this.getRandomColor(),
                avatar: obj.avatar,//弹幕图像
                id:this.itemId++, //弹幕id (系统自动生成)
                danmu_Width,//弹幕宽度
                // 是否是用户手动发送的弹幕？是的话就加一个白色边框
                useradd_border:useradd==true ? '1px solid #e2e1e2':'',
                // 高级弹幕配置参数
                border_radius: obj.border_radius,//圆角
                border: obj.border,//边框色
                background_image: obj.background_image,//背景线性渐变色
                background_image_opacity: obj.background_image_opacity,//背景线性渐变色透明度
                opacity: obj.opacity,//弹幕item透明度（当前发送的弹幕-整体透明度）
            }
            
            // 判断是否可以让弹幕跑起来
            if (this.danmu_unm[num-1].flag==true || useradd==true){
                //console.log('轨道 == ' + num) //需要减1 从0开始
                // 添加 弹幕item 对象到n轨道数组的末尾
                this.danmu_list[num-1].danmu_cell.push(danmuItemText)
                
                // 立即 将轨道flag设置false，用于节流，不可以在发送弹幕，直接过滤掉
                this.danmu_unm[num-1].flag = false
            }else {
                // 已经被过滤掉的弹幕不可以渲染到标签上，这样可以减少内存消耗
                this.danmu_unm[num-1].filter_count++
                let filter_count = this.danmu_unm[num-1].filter_count
                this.filter_count = '轨道_0'+num+'--已过滤 '+filter_count+' 条弹幕'
                //console.log('轨道_0'+num+'--已过滤 '+filter_count+' 条弹幕')
                
                
                // 判断弹幕高度是否大于10，大于10就删除前5条数据，减少内存占用
                this.getDanmu_cell_Shift(num)
            }
            
            
            
            // 老版本
            // await setTimeout(() => {
                
            // }, 100)
            
            // 新版本
            await this.getSetTimeout(100,num).then( res=> {
                // 获取 弹幕n轨道的 轨道cell_id （简称：轨道id）
                let rows_cell_id = this.danmu_list[num - 1].cell_id
                //console.log('轨道id ==' + rows_cell_id)
                
                // 获取 弹幕item 对象属于n轨道的第几项 （n轨道的长度-1）
                let itemIndex = this.danmu_list[num - 1].danmu_cell.length - 1
                //console.log('弹幕item项 ==' + itemIndex)
                
                // 获取 弹幕item 对象属于n轨道的第几项 弹幕id (也就是v-for渲染出来的index)
                let itemId = this.danmu_list[num - 1].danmu_cell[itemIndex].id
                //console.log('弹幕itemId ==' + itemId)
                
                // 获取 弹幕item view标签上绑定的ref值 （:ref="'cell_0'+num+'_pao_'+item.id"）
                let danmu_ref = 'cell_0' + rows_cell_id + '_pao_' + itemId
                //console.log('danmu_ref == ' + danmu_ref)
                
                // 需要延时一下才能获取，因为插入新数据再渲染 是有一个 毫秒级 的用时-时间的
                // 获取当前弹幕的ref
                let el = this.$refs[danmu_ref][0] //必须加[0] 不然获取不到
                // 如果没有获取到el就返回，不然继续向下走弹幕事件是不对的。
                if (!el) return
                
                let options = {
                    el,//弹幕ref
                    num,//轨道id
                    itemIndex,//弹幕索引
                    Width: this.Width,//屏幕宽度
                    danmu_Width: Number(danmuTextLength*this.FontSize),//弹幕宽度（ps：弹幕的长度 * 弹幕字体大小）
                    goscreentime:ScreenTime,//弹幕的头和尾巴进入屏幕可视区需要的时间
                }
                // 执行 弹幕发送 并 弹幕跑起来的移动动画
                this.getDanmu_pao_animation(options).then(res=>{
                    //
                })
                this.getSetTimeout(ScreenTime,num).then(res=>{
                    let res_num = res.num-1
                    //console.log(res_num)
                    this.danmu_unm[res_num].flag = true
                })
                
            })
        },
        
        
        
        /* ===============================
		 * = 弹幕跑起来迁移至animation.js  =
		 * = animation不能加密，加密会失效 =
		 * ===============================
		*/
		
        // 弹幕item开始跑起来
        /* getDanmu_pao_animation(e){
			// 此弹幕只在app端，小程序后续增加
            let ref = e.el
            let num = e.num
            let index = e.itemIndex // + 1 // 由于从0开始
            let slateX = this.getTranslateX(e)
            let durationTime = this.duration //弹幕动画时间
            return new Promise((resolve,reject) =>{
                animation.transition(ref, {
                    styles: {
                        //backgroundColor: '#05DFC7',
                        transform: `translateX(${slateX})`,
                        transformOrigin: 'center center',
                        //opacity:0
                    },
                    duration: durationTime, //ms
                    timingFunction: 'linear',
                    delay: 0 //ms
                }, () => {
                    
                    let options = {
                        ref: ref.attr.id, //弹幕ref-id 
                        num, //轨道id
                        index, //弹幕item项(索引)
                    }
                    resolve(options)
                    // 只要删除数组的第一项，就会有bug，导致出现重叠
                })
            })
        }, */
        // 计算弹幕的transform动画的translateX单位 
        getTranslateX(e){
            let X_px =  -(e.danmu_Width+this.rowGap+this.Width*2+this.avatar_m_right)+'px'
            // 如果弹幕宽度 > 屏幕宽度，
            let slateX = e.danmu_Width <= e.Width ? X_px:'translateX(-100%)'
            //console.log('slateX')
            //console.log(slateX)
            return slateX
        },
        
        // 计算弹幕轨道的弹幕数量是否超过或等于20个，是就删除前10个弹幕，减少内存占用
        getDanmu_cell_Shift(num){
            // 大于等于20条再删除比较好，不然可能弹幕文字短，10条删除前5条，就会看到屏幕在闪烁
            // 判断弹幕高度是否大于20，大于20就删除前10条数据，减少内存占用
            if (this.danmu_list[num-1].danmu_cell.length >= 25){
                for (let i=0; i<10; i++){
                    // 删除会有闪烁问题，解决办法就是进入和退出全屏时先清空所有的弹幕数据
                    //this.danmu_list[num-1].danmu_cell.shift()
                    //console.log('已删除前5个')
                }
                //console.log(this.danmu_list[num-1].danmu_cell)
            }
        },
        
        
        // 计算弹幕轨道的弹幕数量（动态插入到最小的弹幕轨道）
        getDanmu_cell_length() {
            // 获取当前轨道数
            let DanmuCell_Num = this.danmu_cell_num
            let cell_length = []
            for (let i=0; i<DanmuCell_Num; i++){
                cell_length.push(this.danmu_list[i].danmu_cell.length)
            }
            // 返回最小值 （找出最小的值）
            let value = Math.min.apply(null, cell_length)
            let xiangdeng
            // 判断一个数组中所有对象的某个属性全部相等
            if (cell_length.every(item => item === value)){
                //console.log('全相等')
                xiangdeng = true // 全相等时，就随机插入弹幕到n轨道
            }else {
                //console.log('有不等')
                xiangdeng = false //有不等是，就插入到n轨道弹幕数量最少的n轨道
            }
            //console.log(value)
            // 入口参数
            let options = {
                cell_length,
                value,
                xiangdeng,
            }
            return options
            //return length
        },

        

        // 计算随机数（动态插入到不同的轨道）
        randomRange(min, max) { // min最小值，max最大值
            return Math.floor(Math.random() * (max)) + min;
        },
        // 延时时间
        async getSetTimeout(time,num){
            return new Promise((resolve, reject) => {
                this.timeID = setTimeout(() => {
                    // 延时时间到
                    //console.log('成功')
                    // 返回参数
                    let e = {
                        time,
                        num //轨道id
                    }
                    resolve(e)
                    clearTimeout(this.timeID)
                }, time)
            })
        },

        // 计算弹幕的头和尾巴进入屏幕 需要的时间
        getDanmuItem_goScreenTime(e){
            /* duration = 总时间（弹幕持续时间）
             * Width = 屏幕宽度
             * danmu_Width = 弹幕宽度
            */
            let speed //弹幕移动1px距离需要的时间
            let ScreenTime //弹幕头和尾巴进入屏幕可视区需要的时间 
            speed = e.duration / (e.Width + e.danmu_Width)
            // 向上取整
            ScreenTime = Math.ceil(speed * (e.danmu_Width + this.rowGap))
            //console.log('ScreenTime == ' + ScreenTime)
            return ScreenTime
            /* @1   计算弹幕的头和尾巴进入屏幕 需要的时间
            （1.1- 总时间/屏幕宽度+弹幕宽度=speed  移动1px距离需要的时间）
            （1.2-  speed*弹幕宽度+弹幕间距=弹幕头和尾巴进入屏幕可视区时间）
            （1.3-  上一个弹幕没有进入可视区就不能让下一条弹幕进来） */
        },
        
        // 计算n轨道是否没有等待中的弹幕，或者是等待中弹幕数量最小（遍历）
        
        
        
        
        // 计算弹幕文本的长度（字符串长度）
        getDanmuTextbyteLength(DanmuText) {
            //console.log(DanmuText)
            var str = String(DanmuText)
            var count = str.length
            //console.log('弹幕长度 = '+count)
            return count
        },

        


        // 执行添加轨道
        getDanmu_list(e) {
            //this.danmu_list = [] //暂时清空轨道
            var Danmu_list = []
            return new Promise((resolve, reject) => {
                for (let i = 0; i < e; i++) {
                    Danmu_list.push({
                        flag:true,//弹幕过滤器器（当为false时，如果还在执行发送弹幕，那就把这条弹幕记录到过滤总数里，因为false时，是不执行发送弹幕的，自然就不会出现在屏幕可视区）
                        filter_count: 0,//弹幕过滤总数
                        cell_id: i + 1, //弹幕轨道id1
                        danmu_cell: [] //弹幕轨道1 - 弹幕数据
                    })
                }
                resolve(Danmu_list)
            })
        },
        // 执行添加弹幕轨道对应的flag（节流阀）
        getDanmu_unm_flag(e){
            var Danmu_unm = []
            return new Promise((resolve, reject) => {
                for (let i = 0; i < e; i++) {
                    Danmu_unm.push({
                        flag:true,//弹幕过滤器器（当为false时，如果还在执行发送弹幕，那就把这条弹幕记录到过滤总数里，因为false时，是不执行发送弹幕的，自然就不会出现在屏幕可视区）
                        filter_count: 0,//弹幕过滤总数
                    })
                }
                resolve(Danmu_unm)
            })
        },
        
        
        // 清空所有轨道中的弹幕数据
        getDanmu_list_empty(){
            let num = this.danmu_cell_num
            for (let i=0; i<num; i++){
                this.danmu_list[i].danmu_cell = []
            }
        },
        
        
        /* 生成随机颜色[用于弹幕文本] */
        getRandomColor: function() {
            const rgb = []
            for (let i = 0; i < 3; ++i) {
                let color = Math.floor(Math.random() * 256).toString(16)
                color = color.length == 1 ? '0' + color : color
                rgb.push(color)
            }
            return '#' + rgb.join('')
        },
    }
}